/*
* This file is part of Project SkyFire https://www.projectskyfire.org.
* See LICENSE.md file for Copyright information
*/

/// \addtogroup u2w
/// @{
/// \file

#ifndef __WORLDSESSION_H
#define __WORLDSESSION_H

#include "AccountMgr.h"
#include "Authentication/AuthDefines.h"
#include "AddonMgr.h"
#include <atomic>
#include "Common.h"
#include "DatabaseEnv.h"
#include "Object.h"
#include "Opcodes.h"
#include "SharedDefines.h"
#include "World.h"
#include "WorldPacket.h"

class Creature;
class CharacterBooster;
class GameObject;
class InstanceSave;
class Item;
class LoginQueryHolder;
class Object;
class Player;
class Quest;
class SpellCastTargets;
class Unit;
class Warden;
class WorldPacket;
class WorldSocket;
struct AreaTableEntry;
struct AuctionEntry;
struct DeclinedName;
struct ItemTemplate;
struct MovementInfo;

namespace lfg
{
    struct LfgJoinResultData;
    struct LfgPlayerBoot;
    struct LfgProposal;
    struct LfgQueueStatusData;
    struct LfgPlayerRewardData;
    struct LfgRoleCheck;
    struct LfgUpdateData;
}

namespace rbac
{
    class RBACData;
}

enum class AccountDataType
{
    GLOBAL_CONFIG_CACHE = 0,                    // 0x01 g
    PER_CHARACTER_CONFIG_CACHE = 1,                    // 0x02 p
    GLOBAL_BINDINGS_CACHE = 2,                    // 0x04 g
    PER_CHARACTER_BINDINGS_CACHE = 3,                    // 0x08 p
    GLOBAL_MACROS_CACHE = 4,                    // 0x10 g
    PER_CHARACTER_MACROS_CACHE = 5,                    // 0x20 p
    PER_CHARACTER_LAYOUT_CACHE = 6,                    // 0x40 p
    PER_CHARACTER_CHAT_CACHE = 7,                    // 0x80 p
    NUM_ACCOUNT_DATA_TYPES = 8
};


#define GLOBAL_CACHE_MASK           0x15
#define PER_CHARACTER_CACHE_MASK    0xEA

#define REGISTERED_ADDON_PREFIX_SOFTCAP 64

struct AccountData
{
    AccountData() : Time(0), Data("") { }

    time_t Time;
    std::string Data;
};

enum class PartyOperation
{
    PARTY_OP_INVITE = 0,
    PARTY_OP_UNINVITE = 1,
    PARTY_OP_LEAVE = 2,
    PARTY_OP_SWAP = 4
};

enum BFLeaveReason
{
    BF_LEAVE_REASON_CLOSE = 0x00000001,
    //BF_LEAVE_REASON_UNK1      = 0x00000002, (not used)
    //BF_LEAVE_REASON_UNK2      = 0x00000004, (not used)
    BF_LEAVE_REASON_EXITED = 0x00000008,
    BF_LEAVE_REASON_LOW_LEVEL = 0x00000010
};

enum ChatRestrictionType
{
    ERR_CHAT_RESTRICTED = 0,
    ERR_CHAT_THROTTLED = 1,
    ERR_USER_SQUELCHED = 2,
    ERR_YELL_RESTRICTED = 3
};

enum CharterTypes
{
    GUILD_CHARTER_TYPE = 4,
    ARENA_TEAM_CHARTER_2v2_TYPE = 2,
    ARENA_TEAM_CHARTER_3v3_TYPE = 3,
    ARENA_TEAM_CHARTER_5v5_TYPE = 5,
};

enum class BarberShopResult
{
    BARBER_SHOP_SUCCESS = 0,
    BARBER_SHOP_NOT_ENOUGH_MONEY = 1,
    BARBER_SHOP_NOT_SITTING = 2
    /*BARBER_SHOP_NOT_ENOUGH_MONEY = 3*/
};

#define DB2_REPLY_BATTLEPETABILITY             3416538071
#define DB2_REPLY_BATTLEPETABILITYEFFECT       3716901134
#define DB2_REPLY_BATTLEPETABILITYSTATE        1012231747
#define DB2_REPLY_BATTLEPETABILITYTURN         3973639388
#define DB2_REPLY_BATTLEPETBREEDQUALITY        458903206
#define DB2_REPLY_BATTLEPETBREEDSTATE          1794847238
#define DB2_REPLY_BATTLEPETEFFECTPROPERTIES    1672791226
#define DB2_REPLY_BATTLEPETNPCTEAMMEMBER       4060454394
#define DB2_REPLY_BATTLEPETSPECIES             1821637041
#define DB2_REPLY_BATTLEPETSPECIESSTATE        366509520
#define DB2_REPLY_BATTLEPETSPECIESXABILITY     1143173908
#define DB2_REPLY_BATTLEPETSTATE               2403627824
#define DB2_REPLY_BATTLEPETVISUAL              3282955075
#define DB2_REPLY_BROADCASTTEXT                35137211
#define DB2_REPLY_CREATURE                     3386291891
#define DB2_REPLY_CREATUREDIFFICULTY           3386943305
#define DB2_REPLY_CURVE                        1272569722
#define DB2_REPLY_CURVEPOINT                   1880017466
#define DB2_REPLY_DEVICEBLACKLIST              983446676
#define DB2_REPLY_DRIVERBLACKLIST              1326512502
#define DB2_REPLY_GAMEOBJECTS                  331613093
#define DB2_REPLY_ITEM                         1344507586
#define DB2_REPLY_ITEM_SPARSE                  2442913102
#define DB2_REPLY_ITEMCURRENCYCOST             1876974313
#define DB2_REPLY_ITEMEXTENDEDCOST             3146089301
#define DB2_REPLY_ITEMTOBATTLEPET              1563357608
#define DB2_REPLY_ITEMTOMOUNTSPELL             1440631488
#define DB2_REPLY_ITEMUPGRADE                  1879459387
#define DB2_REPLY_KEYCHAIN                     1837770388
#define DB2_REPLY_LOCALE                       1065724855
#define DB2_REPLY_LOCATION                     961296167
#define DB2_REPLY_MAPCHALLENGEMODE             943410215
#define DB2_REPLY_MARKETINGPROMOTIONSXLOCALE   2715021741
#define DB2_REPLY_PATH                         2499044245
#define DB2_REPLY_PATHNODE                     1000230050
#define DB2_REPLY_PATHNODEPROPERTY             4263624740
#define DB2_REPLY_PATHPROPERTY                 149245792
#define DB2_REPLY_QUESTPACKAGEITEM             3425666288
#define DB2_REPLY_RULESETITEMUPGRADE           1840711788
#define DB2_REPLY_RULESETRAIDLOOTUPGRADE       3978279757
#define DB2_REPLY_SCENESCRIPT                  3568395212
#define DB2_REPLY_SCENESCRIPTPACKAGE           3905641993
#define DB2_REPLY_SCENESCRIPTPACKAGEMEMBER     3830298396
#define DB2_REPLY_SPELLEFFECTCAMERASHAKES      1939361897
#define DB2_REPLY_SPELLMISSILE                 1754233351
#define DB2_REPLY_SPELLMISSILEMOTION           930182777 
#define DB2_REPLY_SPELLREAGENTS                2875640223
#define DB2_REPLY_SPELLVISUAL                  4146370265
#define DB2_REPLY_SPELLVISUALEFFECTNAME        48336690  
#define DB2_REPLY_SPELLVISUALKIT               4102286043
#define DB2_REPLY_SPELLVISUALKITAREAMODEL      22642299461
#define DB2_REPLY_SPELLVISUALKITMODELATTACH    4033975491
#define DB2_REPLY_SPELLVISUALMISSILE           1369604944
#define DB2_REPLY_VIGNETTE                     4021368146
#define DB2_REPLY_WBACCESSCONTROLLIST          1477136115
#define DB2_REPLY_WBCERTBLACKLIST              3450573023
#define DB2_REPLY_WBCERTWHITELIST              2287306173
#define DB2_REPLY_WBPERMISSIONS                4163366139

//class to deal with packet processing
//allows to determine if next packet is safe to be processed
class PacketFilter
{
public:
    explicit PacketFilter(WorldSession* pSession) : m_pSession(pSession) { }
    virtual ~PacketFilter() { }

    virtual bool Process(WorldPacket* /*packet*/) { return true; }
    virtual bool ProcessLogout() const { return true; }
    static uint16 DropHighBytes(uint16 opcode) { return opcode & NUM_OPCODE_HANDLERS; }

protected:
    WorldSession* const m_pSession;

private:
    PacketFilter(PacketFilter const& right) = delete;
    PacketFilter& operator=(PacketFilter const& right) = delete;
};
//process only thread-safe packets in Map::Update()
class MapSessionFilter : public PacketFilter
{
public:
    explicit MapSessionFilter(WorldSession* pSession) : PacketFilter(pSession) { }
    ~MapSessionFilter() { }

    virtual bool Process(WorldPacket* packet);
    //in Map::Update() we do not process player logout!
    virtual bool ProcessLogout() const { return false; }
};

//class used to filer only thread-unsafe packets from queue
//in order to update only be used in World::UpdateSessions()
class WorldSessionFilter : public PacketFilter
{
public:
    explicit WorldSessionFilter(WorldSession* pSession) : PacketFilter(pSession) { }
    ~WorldSessionFilter() { }

    virtual bool Process(WorldPacket* packet);
};

// Proxy structure to contain data passed to callback function,
// only to prevent bloating the parameter list
class CharacterCreateInfo
{
    friend class WorldSession;
    friend class Player;

protected:
    CharacterCreateInfo(std::string const& name, uint8 race, uint8 cclass, uint8 gender, uint8 skin, uint8 face, uint8 hairStyle, uint8 hairColor, uint8 facialHair, uint8 outfitId,
        WorldPacket& data) : Name(name), Race(race), Class(cclass), Gender(gender), Skin(skin), Face(face), HairStyle(hairStyle), HairColor(hairColor), FacialHair(facialHair),
        OutfitId(outfitId), Data(data), CharCount(0)
    { }

    /// User specified variables
    std::string Name;
    uint8 Race;
    uint8 Class;
    uint8 Gender;
    uint8 Skin;
    uint8 Face;
    uint8 HairStyle;
    uint8 HairColor;
    uint8 FacialHair;
    uint8 OutfitId;
    WorldPacket Data;

    /// Server side data
    uint8 CharCount;
};

/// Player session in the World
class WorldSession
{
public:
    WorldSession(uint32 id, WorldSocket* sock, AccountTypes sec, uint8 expansion, time_t mute_time, LocaleConstant locale, uint32 recruiter, bool isARecruiter, bool hasBoost);
    ~WorldSession();

    bool PlayerLoading() const { return m_playerLoading; }
    bool PlayerLogout() const { return m_playerLogout; }
    bool PlayerLogoutWithSave() const { return m_playerLogout && m_playerSave; }
    bool PlayerRecentlyLoggedOut() const { return m_playerRecentlyLogout; }
    bool PlayerDisconnected() const { return !m_Socket; }

    void ReadAddonsInfo(WorldPacket& data);
    void SendAddonsInfo();
    void SendTimezoneInformation();
    bool IsAddonRegistered(const std::string& prefix) const;

    void SendPacket(WorldPacket const* packet, bool forced = false);
    void SendNotification(const char* format, ...) ATTR_PRINTF(2, 3);
    void SendNotification(uint32 string_id, ...);
    void SendPetNameInvalid(uint32 error, std::string const& name, DeclinedName* declinedName, uint32 petNumber);
    void SendPartyResult(PartyOperation operation, std::string const& member, PartyResult res, uint32 val = 0);
    void SendSetPhaseShift(std::set<uint32> const& phaseIds, std::set<uint32> const& terrainswaps, std::set<uint32> const& worldAreas);
    void SendQueryTimeResponse();
    void SendGroupInviteNotification(const std::string& inviterName, const std::string& realmName, bool inGroup);
    void SendRolePollInform(ObjectGuid guid, uint8 Index);

    void SendAuthResponse(ResponseCodes code, bool queued, uint32 queuePos = 0);
    void SendClientCacheVersion(uint32 version);

    rbac::RBACData* GetRBACData();
    bool HasPermission(uint32 permissionId);
    void LoadPermissions();
    void InvalidateRBACData(); // Used to force LoadPermissions at next HasPermission check

    void SetVirtualRealmID(uint32 VRealmID) { m_virtualRealmID = VRealmID; }
    uint32 GetVirtualRealmID() const { return m_virtualRealmID; }

    AccountTypes GetSecurity() const { return _security; }
    uint32 GetAccountId() const { return _accountId; }
    Player* GetPlayer() const { return _player; }
    std::string const& GetPlayerName() const;
    std::string GetPlayerInfo() const;

    uint32 GetGuidLow() const;
    void SetSecurity(AccountTypes security) { _security = security; }
    std::string const& GetRemoteAddress() { return m_Address; }
    void SetPlayer(Player* player);
    uint8 Expansion() const { return m_expansion; }

    void InitWarden(SessionKey const&, std::string const& os);

    /// Session in auth.queue currently
    void SetInQueue(bool state) { m_inQueue = state; }

    /// Is the user engaged in a log out process?
    bool isLogingOut() const { return _logoutTime || m_playerLogout; }

    /// Engage the logout process for the user
    void LogoutRequest(time_t requestTime)
    {
        _logoutTime = requestTime;
    }

    /// Is logout cooldown expired?
    bool ShouldLogOut(time_t currTime) const
    {
        return (_logoutTime > 0 && currTime >= _logoutTime + 20);
    }

    void LogoutPlayer(bool save);
    void KickPlayer();

    void QueuePacket(WorldPacket* new_packet);
    bool Update(uint32 diff, PacketFilter& updater);

    /// Handle the authentication waiting queue (to be completed)
    void SendAuthWaitQue(uint32 position);

    // petition query
    void HandlePetitionQueryOpcode(WorldPacket& recvData);
    void SendPetitionQueryOpcode(uint64 petitionguid);

    // name query
    void HandleNameQueryOpcode(WorldPacket& recvPacket);
    void SendNameQueryOpcode(ObjectGuid guid);

    // pet name query
    void HandlePetNameQuery(WorldPacket& recvData);
    void SendPetNameQuery(ObjectGuid guid, uint64 petNumber);

    // realmname query
    void HandleRealmNameQueryOpcode(WorldPacket& recvPacket);
    void SendRealmNameQueryOpcode(uint32 realmId);

    // TODO: trainer hello
    void HandleTrainerListOpcode(WorldPacket& recvPacket);
    void SendTrainerList(uint64 guid);
    void SendTrainerList(uint64 guid, std::string const& strTitle);

    // vendor hello
    void HandleListInventoryOpcode(WorldPacket& recvPacket);
    void SendListInventory(uint64 guid);

    // bank hello
    void HandleBankerActivateOpcode(WorldPacket& recvPacket);
    void SendShowBank(ObjectGuid guid);

    // TODO: tabard hello. client message run away?
    void SendTabardVendorActivate(uint64 guid);

    // spirithealer hello
    void HandleSpiritHealerActivateOpcode(WorldPacket& recvPacket);
    void SendSpiritResurrect();

    // binder hello
    void HandleBinderActivateOpcode(WorldPacket& recvPacket);
    void SendBindPoint(Creature* npc);

    // auctioneer hello
    void HandleAuctionHelloOpcode(WorldPacket& recvPacket);
    void SendAuctionHello(ObjectGuid guid, Creature* unit);

    // Battlemaster hello
    void HandleBattlemasterHelloOpcode(WorldPacket& recvData);
    void SendBattleGroundList(uint64 guid, BattlegroundTypeId bgTypeId = BattlegroundTypeId::BATTLEGROUND_RB);

    // petitioneer hello
    void HandlePetitionShowListOpcode(WorldPacket& recvPacket);
    void SendPetitionShowList(uint64 guid);

    // TODO: attack meele? - sphinx ?
    void HandleAttackSwingOpcode(WorldPacket& recvPacket);
    void SendAttackStop(Unit const* enemy);
    void HandleAttackStopOpcode(WorldPacket& recvPacket);
    void HandlePetStopAttack(WorldPacket& recvData);

    // TODO: trade
    void HandleAcceptTradeOpcode(WorldPacket& recvPacket);
    void HandleBeginTradeOpcode(WorldPacket& recvPacket);
    void HandleBusyTradeOpcode(WorldPacket& recvPacket);
    void HandleCancelTradeOpcode(WorldPacket& recvPacket);
    void HandleClearTradeItemOpcode(WorldPacket& recvPacket);
    void HandleIgnoreTradeOpcode(WorldPacket& recvPacket);
    void HandleInitiateTradeOpcode(WorldPacket& recvPacket);
    void HandleSetTradeGoldOpcode(WorldPacket& recvPacket);
    void HandleSetTradeItemOpcode(WorldPacket& recvPacket);
    void HandleUnacceptTradeOpcode(WorldPacket& recvPacket);
    void SendTradeStatus(TradeStatus status);
    void SendUpdateTrade(bool trader_data = true);
    void SendCancelTrade();

    // Totem
    void SendTotemCreated(ObjectGuid TotemGUID, uint32 Duration, uint32 SpellID, uint8 Slot);

    // TODO: Spell mod cd, used in the core only by Shaman T10 Elemental 2P Bonus and Player::ModifySpellCooldown however ModifySpellCooldown is deadcode...
    void SendModifyCooldown(ObjectGuid UnitGUID, int32 DeltaTime, int32 SpellID);

    // TODO: currently implemented as some kind of block for HandlePetCastSpellOpcode? #burnit!
    void HandleClientCastFlags(WorldPacket& recvPacket, uint8 castFlags, SpellCastTargets& targets);

    // TODO: Pet stable
    void HandleRequestStabledPetsOpcode(WorldPacket& recvPacket);
    void HandleStablePet(WorldPacket& recvPacket);
    void HandleStablePetCallback(PreparedQueryResult result);
    void HandleUnstablePet(WorldPacket& recvPacket);
    void HandleUnstablePetCallback(PreparedQueryResult result, uint32 petId);
    void HandleBuyStableSlot(WorldPacket& recvPacket);
    void HandleStableRevivePet(WorldPacket& recvPacket);
    void HandleStableSwapPet(WorldPacket& recvPacket);
    void HandleStableSwapPetCallback(PreparedQueryResult result, uint32 petId);
    void SendStablePet(uint64 guid);
    void SendStablePetCallback(PreparedQueryResult result, uint64 guid);
    void SendStableResult(uint8 guid);
    bool CheckStableMaster(uint64 guid);

    // Account Data
    AccountData* GetAccountData(AccountDataType type) { return &m_accountData[uint8(type)]; }
    void SetAccountData(AccountDataType type, time_t tm, std::string const& data);
    void SendAccountDataTimes(uint32 mask);
    void LoadGlobalAccountData();
    void LoadAccountData(PreparedQueryResult result, uint32 mask);

    void LoadTutorialsData();
    void SendTutorialsData();
    void SaveTutorialsData(SQLTransaction& trans);
    uint32 GetTutorialInt(uint8 index) const { return m_Tutorials[index]; }
    void SetTutorialInt(uint8 index, uint32 value)
    {
        if (m_Tutorials[index] != value)
        {
            m_Tutorials[index] = value;
            m_TutorialsChanged = true;
        }
    }
    // TODO: auction
    void HandleAuctionListItems(WorldPacket& recvData);
    void HandleAuctionListBidderItems(WorldPacket& recvData);
    void HandleAuctionSellItem(WorldPacket& recvData);
    void HandleAuctionRemoveItem(WorldPacket& recvData);
    void HandleAuctionListOwnerItems(WorldPacket& recvData);
    void HandleAuctionPlaceBid(WorldPacket& recvData);
    void HandleAuctionListPendingSales(WorldPacket& recvData);
    void SendAuctionCommandResult(AuctionEntry* auction, uint32 Action, uint32 ErrorCode, uint32 bidError = 0);
    void SendAuctionBidderNotification(uint32 location, uint32 auctionId, uint64 bidder, uint32 bidSum, uint32 diff, uint32 item_template);
    void SendAuctionOwnerNotification(AuctionEntry* auction);
    void SendAuctionRemovedNotification(uint32 auctionId, uint32 itemEntry, int32 randomPropertyId);

    //Item Enchantment
    void SendEnchantmentLog(uint64 target, uint64 caster, uint64 itemGuid, uint32 itemId, uint32 enchantId, uint32 enchantmentSlot);
    void SendItemEnchantTimeUpdate(ObjectGuid Playerguid, ObjectGuid Itemguid, uint32 slot, uint32 Duration);

    //Taxi status
    void HandleTaxiNodeStatusQueryOpcode(WorldPacket& recvPacket);
    void SendTaxiStatus(uint64 guid);

    //TODO: Taxi
    void HandleTaxiQueryAvailableNodes(WorldPacket& recvPacket);
    void SendTaxiMenu(Creature* unit);
    void HandleMoveSplineDoneOpcode(WorldPacket& recvPacket);
    void SendDoFlight(uint32 mountDisplayId, uint32 path, uint32 pathNode = 0);
    bool SendLearnNewTaxiNode(Creature* unit);
    void SendDiscoverNewTaxiNode(uint32 nodeid);
    void SendActivateTaxiReply(ActivateTaxiReply reply);
    void HandleActivateTaxiOpcode(WorldPacket& recvPacket);
    void HandleActivateTaxiExpressOpcode(WorldPacket& recvPacket);


    void BuildPartyMemberStatsChangedPacket(Player* player, WorldPacket* data);

    void DoLootRelease(uint64 lguid);

    // Account mute time
    time_t m_muteTime;

    // Locales
    LocaleConstant GetSessionDbcLocale() const { return m_sessionDbcLocale; }
    LocaleConstant GetSessionDbLocaleIndex() const { return m_sessionDbLocaleIndex; }
    const char* GetSkyFireString(int32 entry) const;

    uint32 GetLatency() const { return m_latency; }
    void SetLatency(uint32 latency) { m_latency = latency; }
    void ResetClientTimeDelay() { m_clientTimeDelay = 0; }
    uint32 getDialogStatus(Player* player, Object* questgiver, uint32 defstatus);

    std::atomic<time_t> m_timeOutTime;
    void UpdateTimeOutTime(uint32 diff)
    {
        if (time_t(diff) > m_timeOutTime)
            m_timeOutTime = 0;
        else
            m_timeOutTime -= diff;
    }
    void ResetTimeOutTime() { m_timeOutTime = sWorld->getIntConfig(WorldIntConfigs::CONFIG_SOCKET_TIMEOUTTIME); }
    bool IsConnectionIdle() const { return (m_timeOutTime <= 0 && !m_inQueue); }

    // Recruit-A-Friend Handling
    uint32 GetRecruiterId() const { return recruiterId; }
    bool IsARecruiter() const { return isRecruiter; }

    // Boost
    bool HasBoost() const { return m_hasBoost; }
    void SetBoosting(bool boost, bool saveToDB = true);

    z_stream_s* GetCompressionStream() { return _compressionStream; }

public:                                                 // opcodes handlers
    void Handle_NULL(WorldPacket& recvPacket) const;    // not used
    void Handle_EarlyProccess(WorldPacket& recvPacket); // just mark packets processed in WorldSocket::OnRead
    void Handle_EarlyProccessContinued(WorldPacket& recvPacket); //Found in sniffs
    void Handle_Deprecated(WorldPacket& recvPacket) const;    // never used anymore by client

    void HandleCharEnumOpcode(WorldPacket& recvPacket);
    void HandleCharDeleteOpcode(WorldPacket& recvPacket);
    void HandleCharCreateOpcode(WorldPacket& recvPacket);
    void HandleCharCreateCallback(PreparedQueryResult result, CharacterCreateInfo* createInfo);
    void HandlePlayerLoginOpcode(WorldPacket& recvPacket);
    void HandleLoadScreenOpcode(WorldPacket& recvPacket);
    void HandleCharEnum(PreparedQueryResult result);
    void HandlePlayerLogin(LoginQueryHolder* holder);
    void HandleCharFactionOrRaceChange(WorldPacket& recvData);
    void HandleRandomizeCharNameOpcode(WorldPacket& recvData);
    void HandleReorderCharacters(WorldPacket& recvData);
    void HandleOpeningCinematic(WorldPacket& recvData);

    // played time
    void HandlePlayedTime(WorldPacket& recvPacket);

    // Boost
    void SendBattlePayDistributionUpdate(uint64 playerGuid, int8 bonusId, int32 bonusFlag, int32 textId, std::string const& bonusText, std::string const& bonusText2);
    void HandleBattleCharBoost(WorldPacket& recvPacket);

    // new
    void HandleMoveUnRootAck(WorldPacket& recvPacket);
    void HandleMoveRootAck(WorldPacket& recvPacket);
    void HandleMoveGravityAck(WorldPacket& recvData);
    void HandleReturnToGraveyard(WorldPacket& recvPacket);

    // new inspect
    void HandleInspectOpcode(WorldPacket& recvPacket);

    // new party stats
    void HandleInspectHonorStatsOpcode(WorldPacket& recvPacket);

    void HandleMoveWaterWalkAck(WorldPacket& recvPacket);
    void HandleFeatherFallAck(WorldPacket& recvData);

    void HandleMoveHoverAck(WorldPacket& recvData);

    void HandleMountSpecialAnimOpcode(WorldPacket& recvdata);

    // character view
    void HandleShowingHelmOpcode(WorldPacket& recvData);
    void HandleShowingCloakOpcode(WorldPacket& recvData);

    // repair
    void HandleRepairItemOpcode(WorldPacket& recvPacket);

    // Knockback
    void HandleMoveKnockBackAck(WorldPacket& recvPacket);

    void HandleMoveTeleportAck(WorldPacket& recvPacket);
    void HandleForceSpeedChangeAck(WorldPacket& recvData);
    void HandleSetCollisionHeightAck(WorldPacket& recvPacket);
    void HandleMovementForceAck(WorldPacket& recvPacket);

    void HandleRepopRequestOpcode(WorldPacket& recvPacket);
    void HandleAutostoreLootItemOpcode(WorldPacket& recvPacket);
    void HandleLootMoneyOpcode(WorldPacket& recvPacket);
    void HandleLootOpcode(WorldPacket& recvPacket);
    void HandleLootReleaseOpcode(WorldPacket& recvPacket);
    void HandleLootMasterGiveOpcode(WorldPacket& recvPacket);
    void HandleWhoOpcode(WorldPacket& recvPacket);
    void HandleLogoutRequestOpcode(WorldPacket& recvPacket);
    void HandlePlayerLogoutOpcode(WorldPacket& recvPacket);
    void HandleLogoutCancelOpcode(WorldPacket& recvPacket);
    void HandleChangeCurrencyFlags(WorldPacket& recvPacket);

    // GM Ticket opcodes
    void HandleGMTicketCreateOpcode(WorldPacket& recvPacket);
    void HandleGMTicketUpdateOpcode(WorldPacket& recvPacket);
    void HandleGMTicketDeleteOpcode(WorldPacket& recvPacket);
    void HandleGMTicketGetTicketOpcode(WorldPacket& recvPacket);
    void HandleGMTicketSystemStatusOpcode(WorldPacket& recvPacket);
    void HandleGMTicketCaseStatusOpcode(WorldPacket& recvPacket);
    void HandleGMSurveySubmit(WorldPacket& recvPacket);
    void HandleReportLag(WorldPacket& recvPacket);
    void HandleGMResponseResolve(WorldPacket& recvPacket);

    // FeedBackSystem
    void HandleSubmitBugOpcode(WorldPacket& recvPacket);
    void HandleSubmitSuggestOpcode(WorldPacket& recvPacket);

    void HandleTogglePvP(WorldPacket& recvPacket);
    void HandleSetPvP(WorldPacket& recvPacket);

    void HandleZoneUpdateOpcode(WorldPacket& recvPacket);
    void HandleSetSelectionOpcode(WorldPacket& recvPacket);
    void HandleStandStateChangeOpcode(WorldPacket& recvPacket);
    void HandleEmoteOpcode(WorldPacket& recvPacket);
    void HandleContactListOpcode(WorldPacket& recvPacket);
    void HandleAddFriendOpcode(WorldPacket& recvPacket);
    void HandleAddFriendOpcodeCallBack(PreparedQueryResult result, std::string const& friendNote);
    void HandleDelFriendOpcode(WorldPacket& recvPacket);
    void HandleAddIgnoreOpcode(WorldPacket& recvPacket);
    void HandleAddIgnoreOpcodeCallBack(PreparedQueryResult result);
    void HandleDelIgnoreOpcode(WorldPacket& recvPacket);
    void HandleSetContactNotesOpcode(WorldPacket& recvPacket);
    void HandleBugOpcode(WorldPacket& recvPacket);

    void HandleAreaTriggerOpcode(WorldPacket& recvPacket);

    void HandleSetFactionAtWar(WorldPacket& recvData);
    void HandleSetFactionNotAtWar(WorldPacket& recvData);
    void HandleSetFactionCheat(WorldPacket& recvData);
    void HandleSetLfgBonusFactionID(WorldPacket& recvData);
    void HandleSetWatchedFactionOpcode(WorldPacket& recvData);
    void HandleSetFactionInactiveOpcode(WorldPacket& recvData);
    void HandleRequestForcedReactionsOpcode(WorldPacket& recvData);

    void HandleUpdateAccountData(WorldPacket& recvPacket);
    void HandleRequestAccountData(WorldPacket& recvPacket);
    void HandleSetActionButtonOpcode(WorldPacket& recvPacket);

    void HandleGameObjectUseOpcode(WorldPacket& recPacket);
    void HandleGameobjectReportUse(WorldPacket& recvPacket);


    void HandleQueryTimeOpcode(WorldPacket& recvPacket);

    void HandleCreatureQueryOpcode(WorldPacket& recvPacket);

    void HandleGameObjectQueryOpcode(WorldPacket& recvPacket);

    void HandleMoveWorldportAckOpcode(WorldPacket& recvPacket);
    void HandleMoveWorldportAckOpcode();                // for server-side calls

    void HandleMovementOpcodes(WorldPacket& recvPacket);
    void HandleSetActiveMoverOpcode(WorldPacket& recvData);
    void HandleMoveNotActiveMover(WorldPacket& recvData);
    void HandleDismissControlledVehicle(WorldPacket& recvData);
    void HandleRequestVehicleExit(WorldPacket& recvData);
    void HandleMoveSetVehicleRecAck(WorldPacket& recvData);
    void HandleChangeSeatsOnControlledVehicle(WorldPacket& recvData);
    void HandleMoveTimeSkippedOpcode(WorldPacket& recvData);

    void HandleRequestRaidInfoOpcode(WorldPacket& recvData);

    void HandleBattlefieldStatusOpcode(WorldPacket& recvData);

    void HandleGroupInviteOpcode(WorldPacket& recvPacket);
    void HandleGroupInviteResponseOpcode(WorldPacket& recvPacket);
    void HandleGroupUninviteGuidOpcode(WorldPacket& recvPacket);
    void HandleGroupSetLeaderOpcode(WorldPacket& recvPacket);
    void HandleGroupSetRolesOpcode(WorldPacket& recvData);
    void HandleGroupDisbandOpcode(WorldPacket& recvPacket);
    void HandleOptOutOfLootOpcode(WorldPacket& recvData);
    void HandleLootMethodOpcode(WorldPacket& recvPacket);
    void HandleLootRoll(WorldPacket& recvData);
    void HandleRequestPartyMemberStatsOpcode(WorldPacket& recvData);
    void HandleRaidTargetUpdateOpcode(WorldPacket& recvData);
    void HandleRaidReadyCheckOpcode(WorldPacket& recvData);
    void HandleRaidReadyCheckConfirmOpcode(WorldPacket& recvData);
    void HandleRaidReadyCheckFinishedOpcode(WorldPacket& recvData);
    void HandleGroupRaidConvertOpcode(WorldPacket& recvData);
    void HandleGroupChangeSubGroupOpcode(WorldPacket& recvData);
    void HandleGroupSwapSubGroupOpcode(WorldPacket& recvData);
    void HandleGroupAssistantLeaderOpcode(WorldPacket& recvData);
    void HandleGroupEveryoneIsAssistantOpcode(WorldPacket& recvData);
    void HandleSetPartyAssignmentOpcode(WorldPacket& recvData);
    void HandleGroupInitiatePollRole(WorldPacket& recvData);

    void HandlePetitionBuyOpcode(WorldPacket& recvData);
    void HandlePetitionShowSignOpcode(WorldPacket& recvData);
    void HandlePetitionRenameOpcode(WorldPacket& recvData);
    void HandlePetitionSignOpcode(WorldPacket& recvData);
    void HandlePetitionDeclineOpcode(WorldPacket& recvData);
    void HandleOfferPetitionOpcode(WorldPacket& recvData);
    void HandleTurnInPetitionOpcode(WorldPacket& recvData);
    void SendPetitionSignResults(ObjectGuid petitionGuid, ObjectGuid playerGuid, uint8 result);

    void HandleGuildQueryOpcode(WorldPacket& recvPacket);
    void HandleGuildInviteOpcode(WorldPacket& recvPacket);
    void HandleGuildRemoveOpcode(WorldPacket& recvPacket);
    void HandleGuildAcceptOpcode(WorldPacket& recvPacket);
    void HandleGuildDeclineOpcode(WorldPacket& recvPacket);
    void HandleGuildEventLogQueryOpcode(WorldPacket& recvPacket);
    void HandleGuildRosterOpcode(WorldPacket& recvPacket);
    void HandleGuildRewardsQueryOpcode(WorldPacket& recvPacket);
    void HandleGuildPromoteOpcode(WorldPacket& recvPacket);
    void HandleGuildDemoteOpcode(WorldPacket& recvPacket);
    void HandleGuildAssignRankOpcode(WorldPacket& recvPacket);
    void HandleGuildLeaveOpcode(WorldPacket& recvPacket);
    void HandleGuildDisbandOpcode(WorldPacket& recvPacket);
    void HandleGuildSetGuildMaster(WorldPacket& recvPacket);
    void HandleGuildReplaceGuildMaster(WorldPacket& recvPacket);
    void HandleGuildMOTDOpcode(WorldPacket& recvPacket);
    void HandleGuildNewsUpdateStickyOpcode(WorldPacket& recvPacket);
    void HandleGuildSetNoteOpcode(WorldPacket& recvPacket);
    void HandleGuildQueryRanksOpcode(WorldPacket& recvPacket);
    void HandleGuildQueryNewsOpcode(WorldPacket& recvPacket);
    void HandleGuildSetRankPermissionsOpcode(WorldPacket& recvPacket);
    void HandleGuildAddRankOpcode(WorldPacket& recvPacket);
    void HandleGuildDelRankOpcode(WorldPacket& recvPacket);
    void HandleGuildChangeInfoTextOpcode(WorldPacket& recvPacket);
    void HandleSaveGuildEmblemOpcode(WorldPacket& recvPacket);
    void HandleGuildRequestPartyState(WorldPacket& recvPacket);
    void HandleGuildRequestMaxDailyXP(WorldPacket& recvPacket);
    void HandleGuildRequestChallengeUpdate(WorldPacket& recvPacket);
    void HandleAutoDeclineGuildInvites(WorldPacket& recvPacket);

    void HandleGuildFinderAddApplication(WorldPacket& recvPacket);
    void HandleGuildFinderBrowse(WorldPacket& recvPacket);
    void HandleGuildFinderDeclineRecruit(WorldPacket& recvPacket);
    void HandleGuildFinderGetApplications(WorldPacket& recvPacket);
    void HandleGuildFinderGetRecruits(WorldPacket& recvPacket);
    void HandleGuildFinderPostRequest(WorldPacket& recvPacket);
    void HandleGuildFinderRemoveApplication(WorldPacket& recvPacket);
    void HandleGuildFinderSetGuildPost(WorldPacket& recvPacket);


    void HandleBuyBankSlotOpcode(WorldPacket& recvPacket);
    void HandleTrainerBuySpellOpcode(WorldPacket& recvPacket);
    void HandleGossipHelloOpcode(WorldPacket& recvPacket);
    void HandleGossipSelectOptionOpcode(WorldPacket& recvPacket);
    void HandleNpcTextQueryOpcode(WorldPacket& recvPacket);

    void SendTrainerBuyFailed(ObjectGuid guid, uint32 spellId, uint32 reason);

    void HandleDuelProposedOpcode(WorldPacket& recvPacket);
    void HandleDuelResponseOpcode(WorldPacket& recvPacket);



    void HandleGetMailList(WorldPacket& recvData);
    void HandleSendMail(WorldPacket& recvData);
    void HandleMailTakeMoney(WorldPacket& recvData);
    void HandleMailTakeItem(WorldPacket& recvData);
    void HandleMailMarkAsRead(WorldPacket& recvData);
    void HandleMailReturnToSender(WorldPacket& recvData);
    void HandleMailDelete(WorldPacket& recvData);
    void HandleItemTextQuery(WorldPacket& recvData);
    void HandleMailCreateTextItem(WorldPacket& recvData);
    void HandleQueryNextMailTime(WorldPacket& recvData);
    void HandleCancelChanneling(WorldPacket& recvData);

    void HandleSplitItemOpcode(WorldPacket& recvPacket);
    void HandleSwapInvItemOpcode(WorldPacket& recvPacket);
    void HandleDestroyItemOpcode(WorldPacket& recvPacket);
    void HandleAutoEquipItemOpcode(WorldPacket& recvPacket);
    void HandleSellItemOpcode(WorldPacket& recvPacket);
    void HandleBuyItemInSlotOpcode(WorldPacket& recvPacket);
    void HandleBuyItemOpcode(WorldPacket& recvPacket);
    void HandleAutoStoreBagItemOpcode(WorldPacket& recvPacket);
    void HandleReadItem(WorldPacket& recvPacket);
    void HandleAutoEquipItemSlotOpcode(WorldPacket& recvPacket);
    void HandleSwapItem(WorldPacket& recvPacket);
    void HandleBuybackItem(WorldPacket& recvPacket);
    void HandleAutoBankItemOpcode(WorldPacket& recvPacket);
    void HandleAutoStoreBankItemOpcode(WorldPacket& recvPacket);
    void HandleWrapItemOpcode(WorldPacket& recvPacket);

    void HandleSetSheathedOpcode(WorldPacket& recvPacket);

    void HandleUseItemOpcode(WorldPacket& recvPacket);
    void HandleOpenItemOpcode(WorldPacket& recvPacket);
    void HandleCastSpellOpcode(WorldPacket& recvPacket);
    void HandleCancelCastOpcode(WorldPacket& recvPacket);
    void HandleCancelAuraOpcode(WorldPacket& recvPacket);
    void HandleCancelGrowthAuraOpcode(WorldPacket& recvPacket);
    void HandleCancelAutoRepeatSpellOpcode(WorldPacket& recvPacket);

    void HandleLearnTalentOpcode(WorldPacket& recvPacket);
    void HandleLearnPreviewTalents(WorldPacket& recvPacket);
    void HandleRespecWipeConfirmOpcode(WorldPacket& recvPacket);
    void HandleUnlearnSkillOpcode(WorldPacket& recvPacket);

    void HandleQuestgiverStatusQueryOpcode(WorldPacket& recvPacket);
    void HandleQuestgiverStatusMultipleQuery(WorldPacket& recvPacket);
    void HandleQuestgiverHelloOpcode(WorldPacket& recvPacket);
    void HandleQuestgiverAcceptQuestOpcode(WorldPacket& recvPacket);
    void HandleQuestgiverQueryQuestOpcode(WorldPacket& recvPacket);
    void HandleQuestgiverChooseRewardOpcode(WorldPacket& recvPacket);
    void HandleQuestgiverRequestRewardOpcode(WorldPacket& recvPacket);
    void HandleQuestQueryOpcode(WorldPacket& recvPacket);
    void HandleQuestgiverCancel(WorldPacket& recvData);
    void HandleQuestLogSwapQuest(WorldPacket& recvData);
    void HandleQuestLogRemoveQuest(WorldPacket& recvData);
    void HandleQuestConfirmAccept(WorldPacket& recvData);
    void HandleQuestgiverCompleteQuest(WorldPacket& recvData);
    void HandleQuestgiverQuestAutoLaunch(WorldPacket& recvPacket);
    void HandlePushQuestToParty(WorldPacket& recvPacket);
    void HandleQuestPushResult(WorldPacket& recvPacket);

    void HandleMessagechatOpcode(WorldPacket& recvPacket);
    void HandleAddonMessagechatOpcode(WorldPacket& recvPacket);
    void SendPlayerNotFoundNotice(std::string const& name);
    void SendPlayerAmbiguousNotice(std::string const& name);
    void SendWrongFactionNotice();
    void SendChatRestrictedNotice(ChatRestrictionType restriction);
    void HandleTextEmoteOpcode(WorldPacket& recvPacket);
    void HandleChatIgnoredOpcode(WorldPacket& recvPacket);

    void HandleUnregisterAddonPrefixesOpcode(WorldPacket& recvPacket);
    void HandleAddonRegisteredPrefixesOpcode(WorldPacket& recvPacket);

    void HandleReclaimCorpseOpcode(WorldPacket& recvPacket);
    void HandleCorpseQueryOpcode(WorldPacket& recvPacket);
    void HandleCorpseMapPositionQuery(WorldPacket& recvPacket);
    void HandleResurrectResponseOpcode(WorldPacket& recvPacket);
    void HandleSummonResponseOpcode(WorldPacket& recvData);

    void HandleJoinChannel(WorldPacket& recvPacket);
    void HandleLeaveChannel(WorldPacket& recvPacket);
    void HandleChannelList(WorldPacket& recvPacket);
    void HandleChannelPassword(WorldPacket& recvPacket);
    void HandleChannelSetOwner(WorldPacket& recvPacket);
    void HandleChannelOwner(WorldPacket& recvPacket);
    void HandleChannelModerator(WorldPacket& recvPacket);
    void HandleChannelUnmoderator(WorldPacket& recvPacket);
    void HandleChannelMute(WorldPacket& recvPacket);
    void HandleChannelUnmute(WorldPacket& recvPacket);
    void HandleChannelInvite(WorldPacket& recvPacket);
    void HandleChannelKick(WorldPacket& recvPacket);
    void HandleChannelBan(WorldPacket& recvPacket);
    void HandleChannelUnban(WorldPacket& recvPacket);
    void HandleChannelAnnouncements(WorldPacket& recvPacket);
    void HandleChannelDeclineInvite(WorldPacket& recvPacket);
    void HandleChannelDisplayListQuery(WorldPacket& recvPacket);
    void HandleGetChannelMemberCount(WorldPacket& recvPacket);

    void HandleCompleteCinematic(WorldPacket& recvPacket);
    void HandleNextCinematicCamera(WorldPacket& recvPacket);

    void HandlePageTextQueryOpcode(WorldPacket& recvPacket);
    void SendPageText(ObjectGuid GameObjectGUID);

    void HandleSceneCompleted(WorldPacket& recvPacket);

    void HandleTutorialFlag(WorldPacket& recvData);
    void HandleTutorialClear(WorldPacket& recvData);
    void HandleTutorialReset(WorldPacket& recvData);

    //Pet
    void HandlePetAction(WorldPacket& recvData);
    void HandlePetActionHelper(Unit* pet, uint64 guid1, uint32 spellid, uint16 flag, uint64 guid2, float x, float y, float z);
    void HandlePetSetAction(WorldPacket& recvData);
    void HandlePetAbandon(WorldPacket& recvData);
    void HandlePetRename(WorldPacket& recvData);
    void HandlePetCancelAuraOpcode(WorldPacket& recvPacket);
    void HandlePetSpellAutocastOpcode(WorldPacket& recvPacket);
    void HandlePetCastSpellOpcode(WorldPacket& recvPacket);
    void HandlePetLearnTalent(WorldPacket& recvPacket);
    void HandleLearnPreviewTalentsPet(WorldPacket& recvPacket);

    void HandleSetActionBarToggles(WorldPacket& recvData);

    void HandleCharRenameOpcode(WorldPacket& recvData);
    void HandleChangePlayerNameOpcodeCallBack(PreparedQueryResult result, std::string const& newName);
    void HandleSetPlayerDeclinedNames(WorldPacket& recvData);
    void HandeSetTalentSpecialization(WorldPacket& recvData);
    void HandleSetPetSpecialization(WorldPacket& recvData);

    void HandleTotemDestroyed(WorldPacket& recvData);
    void HandleDismissCritter(WorldPacket& recvData);

    //Battleground
    void HandleBattlemasterJoinOpcode(WorldPacket& recvData);
    void HandleBattlegroundPlayerPositionsOpcode(WorldPacket& recvData);
    void HandlePVPLogDataOpcode(WorldPacket& recvData);
    void HandleBattleFieldPortOpcode(WorldPacket& recvData);
    void HandleBattlefieldListOpcode(WorldPacket& recvData);
    void HandleBattlefieldLeaveOpcode(WorldPacket& recvData);
    void HandleBattlemasterJoinArena(WorldPacket& recvData);
    void HandleReportPvPAFK(WorldPacket& recvData);
    void HandleRequestPvpOptions(WorldPacket& recvData);
    void HandleRequestPvpReward(WorldPacket& recvData);
    void HandleRequestConquestFormulaConstants(WorldPacket& recvData);

    void HandleWardenDataOpcode(WorldPacket& recvData);
    void HandleWorldTeleportOpcode(WorldPacket& recvData);
    void HandleMinimapPingOpcode(WorldPacket& recvData);
    void HandleRandomRollOpcode(WorldPacket& recvData);
    void HandleFarSightOpcode(WorldPacket& recvData);
    void HandleSetDungeonDifficultyOpcode(WorldPacket& recvData);
    void HandleSetRaidDifficultyOpcode(WorldPacket& recvData);
    void HandleMoveSetCanFlyAckOpcode(WorldPacket& recvData);
    void HandleRealmSplitOpcode(WorldPacket& recvData);
    void HandleTimeSyncResp(WorldPacket& recvData);
    void HandleWhoisOpcode(WorldPacket& recvData);
    void HandleResetInstancesOpcode(WorldPacket& recvData);
    void HandleHearthAndResurrect(WorldPacket& recvData);
    void HandleInstanceLockResponse(WorldPacket& recvPacket);

    // Battlefield
    void HandleBattlefieldRatedInfoRequest(WorldPacket& recvData);
    void SendBfInvitePlayerToWar(uint64 guid, uint32 zoneId, uint32 time);
    void SendBfInvitePlayerToQueue(uint64 guid);
    void SendBfQueueInviteResponse(uint64 guid, uint32 zoneId, bool canQueue = true, bool full = false);
    void SendBfEntered(uint64 guid);
    void SendBfLeaveMessage(uint64 guid, BFLeaveReason reason = BF_LEAVE_REASON_EXITED);
    void HandleBfQueueInviteResponse(WorldPacket& recvData);
    void HandleBfEntryInviteResponse(WorldPacket& recvData);
    void HandleBfExitRequest(WorldPacket& recvData);

    // Looking for Dungeon/Raid
    void HandleLfgSetCommentOpcode(WorldPacket& recvData);
    void HandleLFDGetLockInfoOpcode(WorldPacket& recvData);
    void SendLfgPlayerLockInfo();
    void SendLfgPartyLockInfo();
    void HandleLfgJoinOpcode(WorldPacket& recvData);
    void HandleLfgLeaveOpcode(WorldPacket& recvData);
    void HandleLfgSetRolesOpcode(WorldPacket& recvData);
    void HandleLfgProposalResultOpcode(WorldPacket& recvData);
    void HandleLFDSetBootVoteOpcode(WorldPacket& recvData);
    void HandleLFDTeleportOpcode(WorldPacket& recvData);
    void HandleLfrJoinOpcode(WorldPacket& recvData);
    void HandleLfrLeaveOpcode(WorldPacket& recvData);
    void HandleLfgGetStatus(WorldPacket& recvData);

    void SendLfgUpdateStatus(lfg::LfgUpdateData const& updateData, bool party);
    void SendLfgRoleChosen(uint64 guid, uint8 roles);
    void SendLfgRoleCheckUpdate(lfg::LfgRoleCheck const& pRoleCheck);
    void SendLfgLfrList(bool update);
    void SendLfgJoinResult(lfg::LfgJoinResultData const& joinData);
    void SendLfgQueueStatus(lfg::LfgQueueStatusData const& queueData);
    void SendLfgPlayerReward(lfg::LfgPlayerRewardData const& lfgPlayerRewardData);
    void SendLfgBootProposalUpdate(lfg::LfgPlayerBoot const& boot);
    void SendLfgUpdateProposal(lfg::LfgProposal const& proposal);
    void SendLfgDisabled();
    void SendLfgOfferContinue(uint32 dungeonEntry);
    void SendLfgTeleportError(uint8 err);

    void HandleAreaSpiritHealerQueryOpcode(WorldPacket& recvData);
    void HandleAreaSpiritHealerQueueOpcode(WorldPacket& recvData);
    void HandleCancelMountAuraOpcode(WorldPacket& recvData);
    void HandleSelfResOpcode(WorldPacket& recvData);
    void HandleComplainOpcode(WorldPacket& recvData);
    void HandleRequestPetInfoOpcode(WorldPacket& recvData);

    // Socket gem
    void HandleSocketOpcode(WorldPacket& recvData);
    void SendUpdateSockets(ObjectGuid ItemGUID, Item* item);

    void HandleCancelTempEnchantmentOpcode(WorldPacket& recvData);

    void HandleItemRefundInfoRequest(WorldPacket& recvData);
    void HandleItemRefund(WorldPacket& recvData);
    void SendItemExpirePurchaseRefund(ObjectGuid itemGuid);
    void HandleSetLootSpecialization(WorldPacket& recvData);

    void HandleChannelVoiceOnOpcode(WorldPacket& recvData);
    void HandleVoiceSessionEnableOpcode(WorldPacket& recvData);
    void HandleSetActiveVoiceChannel(WorldPacket& recvData);
    void HandleSetTaxiBenchmarkOpcode(WorldPacket& recvData);

    // Guild Bank
    void HandleGuildPermissions(WorldPacket& recvData);
    void HandleGuildBankMoneyWithdrawn(WorldPacket& recvData);
    void HandleGuildBankerActivate(WorldPacket& recvData);
    void HandleGuildBankQueryTab(WorldPacket& recvData);
    void HandleGuildBankLogQuery(WorldPacket& recvData);
    void HandleGuildBankDepositMoney(WorldPacket& recvData);
    void HandleGuildBankWithdrawMoney(WorldPacket& recvData);
    void HandleGuildBankSwapItems(WorldPacket& recvData);
    void HandleGuildBankTabNote(WorldPacket& recvData);

    void HandleGuildBankUpdateTab(WorldPacket& recvData);
    void HandleGuildBankBuyTab(WorldPacket& recvData);
    void HandleQueryGuildBankTabText(WorldPacket& recvData);
    void HandleSetGuildBankTabText(WorldPacket& recvData);
    void HandleGuildQueryXPOpcode(WorldPacket& recvData);

    // Refer-a-Friend
    void HandleGrantLevel(WorldPacket& recvData);
    void HandleAcceptGrantLevel(WorldPacket& recvData);

    // Calendar
    void HandleCalendarGetCalendar(WorldPacket& recvData);
    void HandleCalendarGetEvent(WorldPacket& recvData);
    void HandleCalendarGuildFilter(WorldPacket& recvData);
    void HandleCalendarAddEvent(WorldPacket& recvData);
    void HandleCalendarUpdateEvent(WorldPacket& recvData);
    void HandleCalendarRemoveEvent(WorldPacket& recvData);
    void HandleCalendarCopyEvent(WorldPacket& recvData);
    void HandleCalendarEventInvite(WorldPacket& recvData);
    void HandleCalendarEventRsvp(WorldPacket& recvData);
    void HandleCalendarEventRemoveInvite(WorldPacket& recvData);
    void HandleCalendarEventStatus(WorldPacket& recvData);
    void HandleCalendarEventModeratorStatus(WorldPacket& recvData);
    void HandleCalendarComplain(WorldPacket& recvData);
    void HandleCalendarGetNumPending(WorldPacket& recvData);
    void HandleCalendarEventSignup(WorldPacket& recvData);

    void SendCalendarRaidLockout(InstanceSave const* save, bool add);
    void SendCalendarRaidLockoutUpdated(InstanceSave const* save);
    void HandleSetSavedInstanceExtend(WorldPacket& recvData);

    // Void Storage
    void HandleVoidStorageUnlock(WorldPacket& recvData);
    void HandleVoidStorageQuery(WorldPacket& recvData);
    void HandleVoidStorageTransfer(WorldPacket& recvData);
    void HandleVoidSwapItem(WorldPacket& recvData);
    void SendVoidStorageTransferResult(VoidTransferError result);

    // Transmogrification
    void HandleTransmogrifyItems(WorldPacket& recvData);

    // Reforge
    void HandleReforgeItemOpcode(WorldPacket& recvData);
    void SendReforgeResult(bool success);

    // BlackMarket
    void HandleBlackMarketHelloOpcode(WorldPacket& recvData);
    void SendBlackMarketHello(ObjectGuid NpcGUID, bool Open);
    void HandleBlackMarketRequestItemOpcode(WorldPacket& recvData);
    void SendBlackMarketRequestItemsResult();

    void HandleBlackMarketBidOnItem(WorldPacket& recvData);
    void SendBlackMarketBidOnItemResult(uint32 ItemID);

    // Miscellaneous
    void HandleSpellClick(WorldPacket& recvData);
    void HandleMirrorImageDataRequest(WorldPacket& recvData);
    void HandleAlterAppearance(WorldPacket& recvData);
    void SendBarberShopResult(BarberShopResult result);

    void HandleCharCustomize(WorldPacket& recvData);
    void HandleQueryInspectAchievements(WorldPacket& recvData);
    void HandleGuildAchievementProgressQuery(WorldPacket& recvData);
    void HandleEquipmentSetSave(WorldPacket& recvData);
    void HandleEquipmentSetDelete(WorldPacket& recvData);
    void HandleEquipmentSetUse(WorldPacket& recvData);
    void HandleWorldStateUITimerUpdate(WorldPacket& recvData);
    void HandleReadyForAccountDataTimes(WorldPacket& recvData);
    void HandleQuestNPCQuery(WorldPacket& recvData);
    void HandleQueryQuestsCompleted(WorldPacket& recvData);
    void HandleQuestPOIQuery(WorldPacket& recvData);
    void HandleEjectPassenger(WorldPacket& data);
    void HandleRideVehicleInteract(WorldPacket& recvData);
    void HandleUpdateProjectilePosition(WorldPacket& recvPacket);
    void HandleRequestHotfix(WorldPacket& recvPacket);
    void HandleUpdateMissileTrajectory(WorldPacket& recvPacket);
    void HandleViolenceLevel(WorldPacket& recvPacket);
    void HandleObjectUpdateFailedOpcode(WorldPacket& recvPacket);
    void HandleSelectFactionOpcode(WorldPacket& recvPacket);
    void HandleDiscardedTimeSyncAcks(WorldPacket& recvData);
    void HandleRequestCategoryCooldowns(WorldPacket& recvPacket);
    void HandleRequestCemeteryList(WorldPacket& recvPacket);

    void SendBroadcastText(uint32 entry);

    int32 HandleEnableNagleAlgorithm();

    // Compact Unit Frames (4.x)
    void HandleSaveCUFProfiles(WorldPacket& recvPacket);
    void SendLoadCUFProfiles();

    // Battle Pets
    void HandlePetBattleStartPvpMatchmaking(WorldPacket& recvData);
    void HandlePetBattleStopPvpMatchmaking(WorldPacket& recvData);
    void HandleBattlePetDelete(WorldPacket& recvData);
    void HandleBattlePetModifyName(WorldPacket& recvData);
    void HandleBattlePetQueryName(WorldPacket& recvData);
    void HandleBattlePetSetBattleSlot(WorldPacket& recvData);
    void HandleBattlePetSetFlags(WorldPacket& recvData);
    void HandleBattlePetSummonCompanion(WorldPacket& recvData);
    void HandleBattlePetWildRequest(WorldPacket& recvData);

    // Titles
    void HandleSetTitleOpcode(WorldPacket& recvData);
    void SendTitleEarned(uint32 TitleIndex);
    void SendTitleLost(uint32 TitleIndex);

    void SendPlayMusic(uint32 SoundKitID);

    void SendCrossedInebriationThreshold(ObjectGuid guid, uint32 ItemID, DrunkenState drunkenState);

private:
    void InitializeQueryCallbackParameters();
    void ProcessQueryCallbacks();

    PreparedQueryResultFuture _charEnumCallback;
    PreparedQueryResultFuture _addIgnoreCallback;
    PreparedQueryResultFuture _stablePetCallback;
    QueryCallback<PreparedQueryResult, std::string> _charRenameCallback;
    QueryCallback<PreparedQueryResult, std::string> _addFriendCallback;
    QueryCallback<PreparedQueryResult, uint32> _unstablePetCallback;
    QueryCallback<PreparedQueryResult, uint32> _stableSwapCallback;
    QueryCallback<PreparedQueryResult, uint64> _sendStabledPetCallback;
    QueryCallback<PreparedQueryResult, CharacterCreateInfo*, true> _charCreateCallback;
    QueryResultHolderFuture _charLoginCallback;

    friend class World;
protected:
    class DosProtection
    {
        friend class World;
    public:
        DosProtection(WorldSession* s) : Session(s), _policy((Policy)sWorld->getIntConfig(WorldIntConfigs::CONFIG_PACKET_SPOOF_POLICY)) { }
        bool EvaluateOpcode(WorldPacket& p) const;
        void AllowOpcode(uint16 opcode, bool allow) { _isOpcodeAllowed[opcode] = allow; }
    protected:
        enum Policy
        {
            POLICY_LOG,
            POLICY_KICK,
            POLICY_BAN,
        };

        bool IsOpcodeAllowed(uint16 opcode) const
        {
            OpcodeStatusMap::const_iterator itr = _isOpcodeAllowed.find(opcode);
            if (itr == _isOpcodeAllowed.end())
                return true;    // No presence in the map indicates this is the first time the opcode was sent this session, so allow

            return itr->second;
        }

        WorldSession* Session;

    private:
        typedef UNORDERED_MAP<uint16, bool> OpcodeStatusMap;
        OpcodeStatusMap _isOpcodeAllowed; // could be bool array, but wouldn't be practical for game versions with non-linear opcodes
        Policy _policy;

        DosProtection(DosProtection const& right) = delete;
        DosProtection& operator=(DosProtection const& right) = delete;
    } AntiDOS;

private:
    // private trade methods
    void moveItems(Item* myItems[], Item* hisItems[]);

    // logging helper
    void LogUnexpectedOpcode(WorldPacket* packet, const char* status, const char* reason) const;
    void LogUnprocessedTail(WorldPacket* packet) const;

    // EnumData helpers
    bool IsLegitCharacterForAccount(uint32 lowGUID)
    {
        return _legitCharacters.find(lowGUID) != _legitCharacters.end();
    }

    // this stores the GUIDs of the characters who can login
    // characters who failed on Player::BuildEnumData shouldn't login
    std::set<uint32> _legitCharacters;

    uint32 m_GUIDLow;                                   // set loggined or recently logout player (while m_playerRecentlyLogout set)
    Player* _player;
    WorldSocket* m_Socket;
    std::string m_Address;

    AccountTypes _security;
    uint32 _accountId;
    uint32 m_virtualRealmID;
    uint8 m_expansion;
    CharacterBooster* m_charBooster;

    typedef std::list<AddonInfo> AddonsList;

    // Warden
    Warden* _warden;                                    // Remains NULL if Warden system is not enabled by config

    time_t _logoutTime;
    bool m_inQueue;                                     // session wait in auth.queue
    bool m_playerLoading;                               // code processed in LoginPlayer
    bool m_playerLogout;                                // code processed in LogoutPlayer
    bool m_playerRecentlyLogout;
    bool m_playerSave;
    LocaleConstant m_sessionDbcLocale;
    LocaleConstant m_sessionDbLocaleIndex;
    uint32 m_latency;
    uint32 m_clientTimeDelay;
    AccountData m_accountData[uint8(AccountDataType::NUM_ACCOUNT_DATA_TYPES)];
    uint32 m_Tutorials[MAX_ACCOUNT_TUTORIAL_VALUES];
    bool   m_TutorialsChanged;
    AddonsList m_addonsList;
    std::vector<std::string> _registeredAddonPrefixes;
    bool _filterAddonMessages;
    uint32 recruiterId;
    bool isRecruiter;
    bool m_hasBoost;
    ACE_Based::LockedQueue<WorldPacket*, ACE_Thread_Mutex> _recvQueue;
    time_t timeLastWhoCommand;
    z_stream_s* _compressionStream;
    rbac::RBACData* _RBACData;
    WorldSession(WorldSession const& right) = delete;
    WorldSession& operator=(WorldSession const& right) = delete;
};
#endif
/// @}
